package com.yydream.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yydream.common.constant.GlobalEnums;
import com.yydream.common.constant.HttpStatus;
import com.yydream.common.utils.PageUtils;
import com.yydream.common.utils.R;
import com.yydream.dto.SysMenuDTO;
import com.yydream.entity.SysMenuEntity;
import com.yydream.entity.SysRoleMenuEntity;
import com.yydream.mapper.SysMenuMapper;
import com.yydream.service.SysMenuService;
import com.yydream.service.SysRoleMenuService;
import com.yydream.vo.SysMenuVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单表服务实现类
 *
 * @author : yydream
 * @date : 2024-6-17
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity> implements SysMenuService {

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public R queryById(Long id) {
        SysMenuEntity sysMenuEntity = this.getById(id);
        SysMenuVo sysMenuVo = new SysMenuVo();
        BeanUtils.copyProperties(sysMenuEntity, sysMenuVo);
        return R.ok().put(sysMenuVo);
    }

    /**
     * 新增数据
     *
     * @param sysMenu 实例对象
     * @return 实例对象
     */
    @Transactional
    public R insert(SysMenuDTO sysMenu) {
        SysMenuEntity sysMenuEntity = new SysMenuEntity();
        BeanUtils.copyProperties(sysMenu, sysMenuEntity);
        this.save(sysMenuEntity);
        List<SysMenuDTO> childMenus = sysMenu.getChildMenus();
        ArrayList<SysRoleMenuEntity> sysRoleMenuEntities = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(childMenus)) {
//            直接保存处理并保存一下直属子集菜单
            List<SysMenuEntity> collect = childMenus.stream().map(c -> {
                SysMenuEntity menuEntity = new SysMenuEntity();
                BeanUtils.copyProperties(c, menuEntity);
                menuEntity.setPid(sysMenuEntity.getId());
                return menuEntity;
            }).collect(Collectors.toList());
            this.saveBatch(collect);
            collect.forEach(c -> {
                SysRoleMenuEntity sysRoleMenuEntity = new SysRoleMenuEntity();
                sysRoleMenuEntity.setRoleId(GlobalEnums.ADMIN_ROLE.getCode());
                sysRoleMenuEntity.setMenuId(c.getId());
                sysRoleMenuEntities.add(sysRoleMenuEntity);
            });
        }
//        新增完菜单直接分配权限给管理员角色
        SysRoleMenuEntity sysRoleMenuEntity = new SysRoleMenuEntity();
        sysRoleMenuEntity.setMenuId(sysMenuEntity.getId());
        sysRoleMenuEntity.setRoleId(GlobalEnums.ADMIN_ROLE.getCode());
        sysRoleMenuEntities.add(sysRoleMenuEntity);
        sysRoleMenuService.saveBatch(sysRoleMenuEntities);
        return R.ok();
    }

    /**
     * 更新数据
     *
     * @param sysMenu 实例对象
     * @return 实例对象
     */
    public R update(SysMenuDTO sysMenu) {
        SysMenuEntity sysMenuEntity = new SysMenuEntity();
        BeanUtils.copyProperties(sysMenu, sysMenuEntity);
        this.updateById(sysMenuEntity);
        return R.ok();
    }

    /**
     * 通过主键删除数据
     *
     * @param ids 主键
     * @return 是否成功
     */
    @Transactional
    public R deleteById(Long[] ids) {
        List<SysMenuEntity> allList = this.list();
        List<Long> allIds = new ArrayList<>();
        for (Long id : ids) {
            allIds.add(id);
            List<Long> longs = loopMenuGetId(allList, id);
            allIds.addAll(longs);
        }
        List<SysMenuEntity> menuEntities = allIds.stream().map(c -> {
            SysMenuEntity sysMenuEntity = new SysMenuEntity();
            sysMenuEntity.setId(c);
            return sysMenuEntity;
        }).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(menuEntities)) {
            return R.error(HttpStatus.PARAM_ERROR);
        }
        boolean b = this.removeBatchByIds(menuEntities);
//        删除了菜单，还要删除与菜单关联的角色关联表的数据
        sysRoleMenuService.remove(new LambdaQueryWrapper<SysRoleMenuEntity>().in(SysRoleMenuEntity::getMenuId, allIds));
        return R.ok().put( b);
    }

    private List<Long> loopMenuGetId(List<SysMenuEntity> allList, Long id) {
        List<Long> collect = allList.stream().filter(c -> c.getPid().equals(id)).map(c -> c.getId()).collect(Collectors.toList());
        List<Long> idsList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(collect) && collect.size() > 0) {
            collect.forEach(c -> {
                idsList.add(c);
                List<Long> longs = loopMenuGetId(allList, c);
                idsList.addAll(longs);
            });
        }
        return idsList;
    }

    @Override
    public R listPage(SysMenuDTO req) {
        LambdaQueryWrapper<SysMenuEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(!StringUtils.isEmpty(req.getName()), SysMenuEntity::getName, req.getName())
                .eq(!StringUtils.isEmpty(req.getPath()), SysMenuEntity::getPath, req.getPath())
                .eq(Objects.nonNull(req.getPermission()), SysMenuEntity::getPermission, req.getPermission())
                .eq(Objects.nonNull(req.getState()), SysMenuEntity::getState, req.getState());
        List<SysMenuEntity> list = this.list(queryWrapper);
        List<SysMenuVo> voList = list.stream().map(c -> {
            SysMenuVo sysMenuVo = new SysMenuVo();
            BeanUtils.copyProperties(c, sysMenuVo);
            return sysMenuVo;
        }).collect(Collectors.toList());
        List<SysMenuVo> parentList = voList.stream().filter(c -> c.getPid() == 0).sorted(Comparator.comparing(SysMenuVo::getSort)).collect(Collectors.toList());
        loopMenu(parentList, voList);
        return R.ok().put( parentList);
    }

    @Override
    public List<SysMenuVo> queryByMenuIds(List<Long> menuIds) {
        LambdaQueryWrapper<SysMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysMenuEntity::getId, menuIds);
        wrapper.eq(SysMenuEntity::getState, 1);
        List<SysMenuEntity> list = this.list(wrapper);
        List<SysMenuVo> sysMenuVos = PageUtils.toList(list, SysMenuVo.class);
        List<SysMenuVo> parentList = sysMenuVos.stream().filter(c -> c.getPid() == 0).sorted(Comparator.comparing(SysMenuVo::getSort)).collect(Collectors.toList());
        loopMenu(parentList, sysMenuVos);
        return parentList;
    }

    public void loopMenu(List<SysMenuVo> list, List<SysMenuVo> allList) {
        if (!CollectionUtil.isEmpty(list)) {
            for (SysMenuVo sysMenuVo : list) {
                List<SysMenuVo> childList = allList.stream().filter(c -> sysMenuVo.getId().equals(c.getPid())).sorted(Comparator.comparing(SysMenuVo::getSort)).collect(Collectors.toList());
                sysMenuVo.setChildList(childList.size() != 0 ? childList : null);
                loopMenu(childList, allList);
            }
        }
    }
}